package com.supreme.nettyapp.generalclient.mqttclient.service;

import com.supreme.nettyapp.generalclient.mqttclient.handler.MqttClientHandler;
import com.supreme.nettyapp.generalclient.mqttclient.handler.MqttClientInitializer;
import com.supreme.nettyapp.generalclient.mqttclient.props.MqttClientProps;
import com.supreme.nettyapp.generalclient.service.NettyChannelService;
import com.supreme.nettyapp.generalclient.service.NettyClientService;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.EventExecutorGroup;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.Optional;

@Service
public class MqttClientService implements NettyClientService, NettyChannelService {

    @Resource
    private MqttClientProps mqttClientProps;

    @Resource
    private MqttClientHandler mqttClientHandler;

    private EventLoopGroup workerGroup;

    private Channel clientChannel;

    @Async(value = "nettyTask")
    @Override
    public void startNettyClient() {
        workerGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(workerGroup);
            bootstrap.channel(NioSocketChannel.class);

            MqttClientInitializer mqttClientInitializer = new MqttClientInitializer(mqttClientHandler);
            bootstrap.handler(mqttClientInitializer);

            ChannelFuture channelFuture = bootstrap.connect(mqttClientProps.getServerHost(), mqttClientProps.getServerPort()).sync();
            clientChannel = channelFuture.channel();
            clientChannel.closeFuture().sync();
        } catch (InterruptedException e) {
            System.out.println("e.getMessage() = " + e.getMessage());
        } finally {
            System.out.println("MqttClientService Shutdown");
        }
    }

    @Override
    public void startNettyClient(String host, int port) {

    }

    @PreDestroy
    @Override
    public void destroyNettyClient() {
        Optional.ofNullable(workerGroup).ifPresent(EventExecutorGroup::shutdownGracefully);
    }

    @Override
    public Channel getChannel() {
        return clientChannel;
    }

    @Override
    public void writeAndFlush(Object msg) {
        clientChannel.writeAndFlush(msg);
    }
}
